{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.10.1+22.gc481461.dirty\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "import folium\n",
    "\n",
    "print(folium.__version__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note** : The examples presented below are the copy of the ones presented on https://github.com/bbecquet/Leaflet.PolylineOffset"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Basic Demo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- The dashed line is the \"model\", with no offset applied. \n",
    "- The Red line is with a -5px offset,\n",
    "- The Green line is with a 10px offset.\n",
    "The three are distinct Polyline objects but uses the same coordinate array"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"about:blank\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" data-html=PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjYuMC9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjYuMC9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF83YzdlZmM5NmQxYTQ0ZGEwYWFiYjE2MjBhZmYwNWE3MSB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9sZWFmbGV0LXBvbHlsaW5lb2Zmc2V0QDEuMS4xL2xlYWZsZXQucG9seWxpbmVvZmZzZXQubWluLmpzIj48L3NjcmlwdD4KPC9oZWFkPgo8Ym9keT4gICAgCiAgICAKICAgICAgICAgICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF83YzdlZmM5NmQxYTQ0ZGEwYWFiYjE2MjBhZmYwNWE3MSIgPjwvZGl2PgogICAgICAgIAo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAgICAgICAgIHZhciBtYXBfN2M3ZWZjOTZkMWE0NGRhMGFhYmIxNjIwYWZmMDVhNzEgPSBMLm1hcCgKICAgICAgICAgICAgICAgICJtYXBfN2M3ZWZjOTZkMWE0NGRhMGFhYmIxNjIwYWZmMDVhNzEiLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGNlbnRlcjogWzU4LjAsIC0xMS4wXSwKICAgICAgICAgICAgICAgICAgICBjcnM6IEwuQ1JTLkVQU0czODU3LAogICAgICAgICAgICAgICAgICAgIHpvb206IDQsCiAgICAgICAgICAgICAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgcHJlZmVyQ2FudmFzOiBmYWxzZSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKTsKCiAgICAgICAgICAgIAoKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl9jNDdkYmMyYzExYjE0ZTBiYjkwY2UxZGZkOGI4YmRhNSA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgImh0dHBzOi8vY2FydG9kYi1iYXNlbWFwcy17c30uZ2xvYmFsLnNzbC5mYXN0bHkubmV0L2xpZ2h0X2FsbC97en0ve3h9L3t5fS5wbmciLAogICAgICAgICAgICAgICAgeyJhdHRyaWJ1dGlvbiI6ICJcdTAwMjZjb3B5OyBcdTAwM2NhIGhyZWY9XCJodHRwOi8vd3d3Lm9wZW5zdHJlZXRtYXAub3JnL2NvcHlyaWdodFwiXHUwMDNlT3BlblN0cmVldE1hcFx1MDAzYy9hXHUwMDNlIGNvbnRyaWJ1dG9ycyBcdTAwMjZjb3B5OyBcdTAwM2NhIGhyZWY9XCJodHRwOi8vY2FydG9kYi5jb20vYXR0cmlidXRpb25zXCJcdTAwM2VDYXJ0b0RCXHUwMDNjL2FcdTAwM2UsIENhcnRvREIgXHUwMDNjYSBocmVmID1cImh0dHA6Ly9jYXJ0b2RiLmNvbS9hdHRyaWJ1dGlvbnNcIlx1MDAzZWF0dHJpYnV0aW9uc1x1MDAzYy9hXHUwMDNlIiwgImRldGVjdFJldGluYSI6IGZhbHNlLCAibWF4TmF0aXZlWm9vbSI6IDE4LCAibWF4Wm9vbSI6IDE4LCAibWluWm9vbSI6IDAsICJub1dyYXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic3ViZG9tYWlucyI6ICJhYmMiLCAidG1zIjogZmFsc2V9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzdjN2VmYzk2ZDFhNDRkYTBhYWJiMTYyMGFmZjA1YTcxKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF8yODBjNTVhODZjOGY0N2FjOTM3OWY2ZDA5MGFkMjQ1ZiA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzU4LjQ0NzczLCAtMjguNjUyMzRdLCBbNTMuMCwgLTIzLjMzNDk2XSwgWzUzLjAsIC0xNC4zMjYxN10sIFs1OC4xNzA3LCAtMTAuMzcxMDldLCBbNTkuMCwgLTEzLjBdLCBbNTcuMCwgLTE1LjBdLCBbNTcuMCwgLTE4LjBdLCBbNjAuMCwgLTE4LjBdLCBbNjMuMCwgLTUuMF0sIFs1OS4wLCAtNy4wXSwgWzU4LjAsIC0zLjBdLCBbNTYuMCwgLTMuMF0sIFs2MC4wLCAtNC4wXV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiYmxhY2siLCAiZGFzaEFycmF5IjogIjUsMTAiLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiYmxhY2siLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvZmZzZXQiOiAwLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogMn0KICAgICAgICAgICAgKS5hZGRUbyhtYXBfN2M3ZWZjOTZkMWE0NGRhMGFhYmIxNjIwYWZmMDVhNzEpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfb2Zmc2V0XzFjMmU2YTI5MmYxZjRmMGU4OWM2MzYzNjNiMjY0YzQyID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNTguNDQ3NzMsIC0yOC42NTIzNF0sIFs1My4wLCAtMjMuMzM0OTZdLCBbNTMuMCwgLTE0LjMyNjE3XSwgWzU4LjE3MDcsIC0xMC4zNzEwOV0sIFs1OS4wLCAtMTMuMF0sIFs1Ny4wLCAtMTUuMF0sIFs1Ny4wLCAtMTguMF0sIFs2MC4wLCAtMTguMF0sIFs2My4wLCAtNS4wXSwgWzU5LjAsIC03LjBdLCBbNTguMCwgLTMuMF0sIFs1Ni4wLCAtMy4wXSwgWzYwLjAsIC00LjBdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZjAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjZjAwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogLTUsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF83YzdlZmM5NmQxYTQ0ZGEwYWFiYjE2MjBhZmYwNWE3MSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9vZmZzZXRfMjUyYTFmMDJjZGQ2NDVmZjlhNzk3N2UxMDk1OWQ3YzMgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s1OC40NDc3MywgLTI4LjY1MjM0XSwgWzUzLjAsIC0yMy4zMzQ5Nl0sIFs1My4wLCAtMTQuMzI2MTddLCBbNTguMTcwNywgLTEwLjM3MTA5XSwgWzU5LjAsIC0xMy4wXSwgWzU3LjAsIC0xNS4wXSwgWzU3LjAsIC0xOC4wXSwgWzYwLjAsIC0xOC4wXSwgWzYzLjAsIC01LjBdLCBbNTkuMCwgLTcuMF0sIFs1OC4wLCAtMy4wXSwgWzU2LjAsIC0zLjBdLCBbNjAuMCwgLTQuMF1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwODAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwODAiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvZmZzZXQiOiAxMCwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDN9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzdjN2VmYzk2ZDFhNDRkYTBhYWJiMTYyMGFmZjA1YTcxKTsKICAgICAgICAKPC9zY3JpcHQ+ onload=\"this.contentDocument.open();this.contentDocument.write(atob(this.getAttribute('data-html')));this.contentDocument.close();\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x1f6686d2bc8>"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from folium import plugins\n",
    "\n",
    "\n",
    "m = folium.Map(location=[58.0, -11.0], zoom_start=4, tiles=\"cartodbpositron\")\n",
    "\n",
    "coords = [\n",
    "    [58.44773, -28.65234],\n",
    "    [53, -23.33496],\n",
    "    [53, -14.32617],\n",
    "    [58.1707, -10.37109],\n",
    "    [59, -13],\n",
    "    [57, -15],\n",
    "    [57, -18],\n",
    "    [60, -18],\n",
    "    [63, -5],\n",
    "    [59, -7],\n",
    "    [58, -3],\n",
    "    [56, -3],\n",
    "    [60, -4],\n",
    "]\n",
    "\n",
    "plugins.PolyLineOffset(\n",
    "    coords, weight=2, dash_array=\"5,10\", color=\"black\", opacity=1\n",
    ").add_to(m)\n",
    "\n",
    "plugins.PolyLineOffset(coords, color=\"#f00\", opacity=1, offset=-5).add_to(m)\n",
    "\n",
    "plugins.PolyLineOffset(coords, color=\"#080\", opacity=1, offset=10).add_to(m)\n",
    "\n",
    "m.save(os.path.join('results', \"PolyLineOffset_simple.html\"))\n",
    "\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Bus Lines"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A more complex demo. \n",
    "Offsets are computed automatically depending on the number of bus lines using the same segment.\n",
    "Other non-offset polylines are used to achieve the white and black outline effect."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"about:blank\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" data-html=PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjYuMC9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjYuMC9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF8zNjkwNjcwZjA4NDE0Mjg3YWMxZmY3ZGNkYjBlZDVmOCB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9sZWFmbGV0LXBvbHlsaW5lb2Zmc2V0QDEuMS4xL2xlYWZsZXQucG9seWxpbmVvZmZzZXQubWluLmpzIj48L3NjcmlwdD4KPC9oZWFkPgo8Ym9keT4gICAgCiAgICAKICAgICAgICAgICAgPGRpdiBjbGFzcz0iZm9saXVtLW1hcCIgaWQ9Im1hcF8zNjkwNjcwZjA4NDE0Mjg3YWMxZmY3ZGNkYjBlZDVmOCIgPjwvZGl2PgogICAgICAgIAo8L2JvZHk+CjxzY3JpcHQ+ICAgIAogICAgCiAgICAgICAgICAgIHZhciBtYXBfMzY5MDY3MGYwODQxNDI4N2FjMWZmN2RjZGIwZWQ1ZjggPSBMLm1hcCgKICAgICAgICAgICAgICAgICJtYXBfMzY5MDY3MGYwODQxNDI4N2FjMWZmN2RjZGIwZWQ1ZjgiLAogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGNlbnRlcjogWzQ4Ljg2OCwgMi4zNjVdLAogICAgICAgICAgICAgICAgICAgIGNyczogTC5DUlMuRVBTRzM4NTcsCiAgICAgICAgICAgICAgICAgICAgem9vbTogMTUsCiAgICAgICAgICAgICAgICAgICAgem9vbUNvbnRyb2w6IHRydWUsCiAgICAgICAgICAgICAgICAgICAgcHJlZmVyQ2FudmFzOiBmYWxzZSwKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgKTsKCiAgICAgICAgICAgIAoKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgdGlsZV9sYXllcl81NzZkOTljNGZjZjk0YWNkYWNhMWE0NmNmYWZmNWM5NiA9IEwudGlsZUxheWVyKAogICAgICAgICAgICAgICAgImh0dHBzOi8ve3N9LnRpbGUub3BlbnN0cmVldG1hcC5vcmcve3p9L3t4fS97eX0ucG5nIiwKICAgICAgICAgICAgICAgIHsiYXR0cmlidXRpb24iOiAiRGF0YSBieSBcdTAwMjZjb3B5OyBcdTAwM2NhIGhyZWY9XCJodHRwOi8vb3BlbnN0cmVldG1hcC5vcmdcIlx1MDAzZU9wZW5TdHJlZXRNYXBcdTAwM2MvYVx1MDAzZSwgdW5kZXIgXHUwMDNjYSBocmVmPVwiaHR0cDovL3d3dy5vcGVuc3RyZWV0bWFwLm9yZy9jb3B5cmlnaHRcIlx1MDAzZU9EYkxcdTAwM2MvYVx1MDAzZS4iLCAiZGV0ZWN0UmV0aW5hIjogZmFsc2UsICJtYXhOYXRpdmVab29tIjogMTgsICJtYXhab29tIjogMTgsICJtaW5ab29tIjogMCwgIm5vV3JhcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzdWJkb21haW5zIjogImFiYyIsICJ0bXMiOiBmYWxzZX0KICAgICAgICAgICAgKS5hZGRUbyhtYXBfMzY5MDY3MGYwODQxNDI4N2FjMWZmN2RjZGIwZWQ1ZjgpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBmZWF0dXJlX2dyb3VwX2IxMDZlMWI4ODVhNzRiMTY4MTIzNTVjMGNhMWExZjZmID0gTC5mZWF0dXJlR3JvdXAoCiAgICAgICAgICAgICAgICB7fQogICAgICAgICAgICApLmFkZFRvKG1hcF8zNjkwNjcwZjA4NDE0Mjg3YWMxZmY3ZGNkYjBlZDVmOCk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9iMzI1NzhjMjY5YzM0Mzg2Yjc4Y2Q3YjBkZTc3MmMyNyA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg3NjIxNzczMzI0MTUzLCAyLjM1NzkxOTIxNjE1NjAwNl0sIFs0OC44NzQ4MzQ2OTM3MzE2NjQsIDIuMzU3MzM5ODU5MDA4Nzg5XSwgWzQ4Ljg2ODU1NDA4NDMyNzQ5LCAyLjM2Mjk4MzIyNjc3NjEyM10sIFs0OC44Njc5NjEyNjY5OTE2OCwgMi4zNjIzODI0MTE5NTY3ODddLCBbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M11dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwMDAiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAxOX0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwX2IxMDZlMWI4ODVhNzRiMTY4MTIzNTVjMGNhMWExZjZmKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lXzFlMmVkMmRlZDA0ZjRmOTU5YTJhNDBjMjViYmFiOGY1ID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY0NDM5NTA0OTM4MjMsIDIuMzUxNTAzMzcyMTkyMzgzXSwgWzQ4Ljg2Njc3NTYxMTI1MDIwNSwgMi4zNjE2MDk5MzU3NjA0OThdLCBbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M11dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwMDAiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAxOX0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwX2IxMDZlMWI4ODVhNzRiMTY4MTIzNTVjMGNhMWExZjZmKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX2Y0YTVmNjZmMTZmMzQ5YTU4YWFlZDRiNzczNTRiYjIzID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY2MTkxNTk0ODk2MDMsIDIuMzY5NjI3MDU4NTA2MDEyXSwgWzQ4Ljg2MjYzOTcxMTIwNDIsIDIuMzcyNDAzMTQ0ODM2NDI1M10sIFs0OC44NjE2MjMzMjg1MDAxLCAyLjM3MjgzMjI5ODI3ODgwODZdLCBbNDguODYwODA0NTYwNzU1NjcsIDIuMzcyNzY3OTI1MjYyNDUxXV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiIzAwMCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDE5fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfYjEwNmUxYjg4NWE3NGIxNjgxMjM1NWMwY2ExYTFmNmYpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfMDYxMDYyM2MyNzI2NDY1NDhlNjQ5ZGQ2YTMyZDYzMmEgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XSwgWzQ4Ljg2NjMwOTgxMDIzNjk0LCAyLjM2NDc2NDIxMzU2MjAxMTddLCBbNDguODYzMTQ3ODk0ODE2MTIsIDIuMzY2NjczOTQ2MzgwNjE1Ml0sIFs0OC44NjA2NjMzOTI1NDk0NCwgMi4zNjczMTc2NzY1NDQxODk1XV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiIzAwMCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDEyfQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfYjEwNmUxYjg4NWE3NGIxNjgxMjM1NWMwY2ExYTFmNmYpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfY2M0ZDE2NTc0ZWFkNDBjNDk1MTc1YjRjODY5OWE0MTEgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjczNTQzMjc2ODEzMSwgMi4zNjMzMjY1NDk1MzAwMjkzXSwgWzQ4Ljg2NjUzNTY1MzY5Mzk2LCAyLjM2NDc0Mjc1NTg4OTg5MjZdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMDAwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogMzN9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF9iMTA2ZTFiODg1YTc0YjE2ODEyMzU1YzBjYTFhMWY2Zik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV82MDhiZGRkMDU0MDk0NjhmYTU2Njg5ZTZiYTNlZDQxNSA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NjUzNTY1MzY5Mzk2LCAyLjM2NDc0Mjc1NTg4OTg5MjZdLCBbNDguODY2NjA2MjI5NTY1MjQsIDIuMzY1MDAwMjQ3OTU1MzIyM10sIFs0OC44NjY5ODczMzc1NTAxNjQsIDIuMzY1NTA5ODY3NjY4MTUyXSwgWzQ4Ljg2NjE5MTU5NDg5NjAzLCAyLjM2OTYyNzA1ODUwNjAxMl1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwMDAiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAyNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwX2IxMDZlMWI4ODVhNzRiMTY4MTIzNTVjMGNhMWExZjZmKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lXzQ4NzlmNTg0ZDY4YTRiODk5ZDM2NDgwNWZhMDgyYmMwID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY2MTkxNTk0ODk2MDMsIDIuMzY5NjI3MDU4NTA2MDEyXSwgWzQ4Ljg2NTcwMjg1MDg5NTc0NCwgMi4zNzIzNDk1MDA2NTYxMjhdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMDAwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogMTJ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF9iMTA2ZTFiODg1YTc0YjE2ODEyMzU1YzBjYTFhMWY2Zik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGZlYXR1cmVfZ3JvdXBfOWFiYmVjMjFlMGRjNGMwMGJmZWJjNWVkMjM5MzA4N2IgPSBMLmZlYXR1cmVHcm91cCgKICAgICAgICAgICAgICAgIHt9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzM2OTA2NzBmMDg0MTQyODdhYzFmZjdkY2RiMGVkNWY4KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lXzk3NWQzYzFkOWM5YjRmNTg5ZjJiNGY1MzlmMTA3ZmZjID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODc2MjE3NzMzMjQxNTMsIDIuMzU3OTE5MjE2MTU2MDA2XSwgWzQ4Ljg3NDgzNDY5MzczMTY2NCwgMi4zNTczMzk4NTkwMDg3ODldLCBbNDguODY4NTU0MDg0MzI3NDksIDIuMzYyOTgzMjI2Nzc2MTIzXSwgWzQ4Ljg2Nzk2MTI2Njk5MTY4LCAyLjM2MjM4MjQxMTk1Njc4N10sIFs0OC44NjczNTQzMjc2ODEzMSwgMi4zNjMzMjY1NDk1MzAwMjkzXV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2ZmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiI2ZmZiIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDE3fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfOWFiYmVjMjFlMGRjNGMwMGJmZWJjNWVkMjM5MzA4N2IpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfOTUzMjk2YTE4NGQwNDE3NTliMzU3NzI3YmI1Mzg1ZWQgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjQ0Mzk1MDQ5MzgyMywgMi4zNTE1MDMzNzIxOTIzODNdLCBbNDguODY2Nzc1NjExMjUwMjA1LCAyLjM2MTYwOTkzNTc2MDQ5OF0sIFs0OC44NjczNTQzMjc2ODEzMSwgMi4zNjMzMjY1NDk1MzAwMjkzXV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2ZmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiI2ZmZiIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDE3fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfOWFiYmVjMjFlMGRjNGMwMGJmZWJjNWVkMjM5MzA4N2IpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfMjI0NDBiOGE4NjRmNDRlOWIwNzA2ODlkZWMxZjlhMzAgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjYxOTE1OTQ4OTYwMywgMi4zNjk2MjcwNTg1MDYwMTJdLCBbNDguODYyNjM5NzExMjA0MiwgMi4zNzI0MDMxNDQ4MzY0MjUzXSwgWzQ4Ljg2MTYyMzMyODUwMDEsIDIuMzcyODMyMjk4Mjc4ODA4Nl0sIFs0OC44NjA4MDQ1NjA3NTU2NywgMi4zNzI3Njc5MjUyNjI0NTFdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZmZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjZmZmIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogMTd9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF85YWJiZWMyMWUwZGM0YzAwYmZlYmM1ZWQyMzkzMDg3Yik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV84ZDJlYWVmYmVjMmM0ZmQ2OGY0ODFkOGNjZGVlNWE2OCA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NjUzNTY1MzY5Mzk2LCAyLjM2NDc0Mjc1NTg4OTg5MjZdLCBbNDguODY2MzA5ODEwMjM2OTQsIDIuMzY0NzY0MjEzNTYyMDExN10sIFs0OC44NjMxNDc4OTQ4MTYxMiwgMi4zNjY2NzM5NDYzODA2MTUyXSwgWzQ4Ljg2MDY2MzM5MjU0OTQ0LCAyLjM2NzMxNzY3NjU0NDE4OTVdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZmZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjZmZmIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogMTB9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF85YWJiZWMyMWUwZGM0YzAwYmZlYmM1ZWQyMzkzMDg3Yik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV8xYzk3NDIzN2U5YjE0NTk5OTI2YmYzMjBkNDRiMDNhNyA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdLCBbNDguODY2NTM1NjUzNjkzOTYsIDIuMzY0NzQyNzU1ODg5ODkyNl1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNmZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiNmZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzMX0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzlhYmJlYzIxZTBkYzRjMDBiZmViYzVlZDIzOTMwODdiKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lXzNjNzdmNjQ1MTYyNzQ2MmZhZWM0OWM3MTUxMTNhZDFmID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY2NTM1NjUzNjkzOTYsIDIuMzY0NzQyNzU1ODg5ODkyNl0sIFs0OC44NjY2MDYyMjk1NjUyNCwgMi4zNjUwMDAyNDc5NTUzMjIzXSwgWzQ4Ljg2Njk4NzMzNzU1MDE2NCwgMi4zNjU1MDk4Njc2NjgxNTJdLCBbNDguODY2MTkxNTk0ODk2MDMsIDIuMzY5NjI3MDU4NTA2MDEyXV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiI2ZmZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiI2ZmZiIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDI0fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfOWFiYmVjMjFlMGRjNGMwMGJmZWJjNWVkMjM5MzA4N2IpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfNzE5NmVlNDA2ZmRlNDA0MTgxYzZhOGE1YzdkNmQ4MjYgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjYxOTE1OTQ4OTYwMywgMi4zNjk2MjcwNTg1MDYwMTJdLCBbNDguODY1NzAyODUwODk1NzQ0LCAyLjM3MjM0OTUwMDY1NjEyOF1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNmZmYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiNmZmYiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAxMH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzlhYmJlYzIxZTBkYzRjMDBiZmViYzVlZDIzOTMwODdiKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgZmVhdHVyZV9ncm91cF82NmQzYjM4YjRiNDM0OGNmYTkwNDAwYmFmYjUwYTQ1NSA9IEwuZmVhdHVyZUdyb3VwKAogICAgICAgICAgICAgICAge30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfMzY5MDY3MGYwODQxNDI4N2FjMWZmN2RjZGIwZWQ1ZjgpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfb2Zmc2V0X2RmYTk4Mzc0MGM3ZjQyMzBiOTY0Y2I3MDhlOTIwMjYyID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODc2MjE3NzMzMjQxNTMsIDIuMzU3OTE5MjE2MTU2MDA2XSwgWzQ4Ljg3NDgzNDY5MzczMTY2NCwgMi4zNTczMzk4NTkwMDg3ODldLCBbNDguODY4NTU0MDg0MzI3NDksIDIuMzYyOTgzMjI2Nzc2MTIzXSwgWzQ4Ljg2Nzk2MTI2Njk5MTY4LCAyLjM2MjM4MjQxMTk1Njc4N10sIFs0OC44NjczNTQzMjc2ODEzMSwgMi4zNjMzMjY1NDk1MzAwMjkzXV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAicmVkIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICJyZWQiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvZmZzZXQiOiAtMy41LCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzY2ZDNiMzhiNGI0MzQ4Y2ZhOTA0MDBiYWZiNTBhNDU1KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF8zMjAwZDgxYzEwZjc0NzcxYWQwMThmZTNkODI5MDliMCA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg3NjIxNzczMzI0MTUzLCAyLjM1NzkxOTIxNjE1NjAwNl0sIFs0OC44NzQ4MzQ2OTM3MzE2NjQsIDIuMzU3MzM5ODU5MDA4Nzg5XSwgWzQ4Ljg2ODU1NDA4NDMyNzQ5LCAyLjM2Mjk4MzIyNjc3NjEyM10sIFs0OC44Njc5NjEyNjY5OTE2OCwgMi4zNjIzODI0MTE5NTY3ODddLCBbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M11dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwOGYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwOGYiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvZmZzZXQiOiAzLjUsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA2fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfNjZkM2IzOGI0YjQzNDhjZmE5MDQwMGJhZmI1MGE0NTUpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfb2Zmc2V0X2ExYTQwNGI1NTE1YzQxZmRhMTgxYzBlY2M4ZmM5ODQ5ID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY0NDM5NTA0OTM4MjMsIDIuMzUxNTAzMzcyMTkyMzgzXSwgWzQ4Ljg2Njc3NTYxMTI1MDIwNSwgMi4zNjE2MDk5MzU3NjA0OThdLCBbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M11dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwYzAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwYzAiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvZmZzZXQiOiAtMy41LCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzY2ZDNiMzhiNGI0MzQ4Y2ZhOTA0MDBiYWZiNTBhNDU1KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF82MDExYTgyZTNhOTI0NzQyYTU3MmYwZGIzMzhlM2MzOCA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NDQzOTUwNDkzODIzLCAyLjM1MTUwMzM3MjE5MjM4M10sIFs0OC44NjY3NzU2MTEyNTAyMDUsIDIuMzYxNjA5OTM1NzYwNDk4XSwgWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZjgwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjZjgwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogMy41LCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzY2ZDNiMzhiNGI0MzQ4Y2ZhOTA0MDBiYWZiNTBhNDU1KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF9lOWEyYTYwNzUxZTA0ZjQ2OTY0YmQxODIwOWI3MDdhZiA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NjE5MTU5NDg5NjAzLCAyLjM2OTYyNzA1ODUwNjAxMl0sIFs0OC44NjI2Mzk3MTEyMDQyLCAyLjM3MjQwMzE0NDgzNjQyNTNdLCBbNDguODYxNjIzMzI4NTAwMSwgMi4zNzI4MzIyOTgyNzg4MDg2XSwgWzQ4Ljg2MDgwNDU2MDc1NTY3LCAyLjM3Mjc2NzkyNTI2MjQ1MV1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwOGYiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwOGYiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvZmZzZXQiOiAtMy41LCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzY2ZDNiMzhiNGI0MzQ4Y2ZhOTA0MDBiYWZiNTBhNDU1KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF9hYjgyMDllMWFmMTc0MTUzODIwZWZmNGVmMDg2OGNkOSA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NjE5MTU5NDg5NjAzLCAyLjM2OTYyNzA1ODUwNjAxMl0sIFs0OC44NjI2Mzk3MTEyMDQyLCAyLjM3MjQwMzE0NDgzNjQyNTNdLCBbNDguODYxNjIzMzI4NTAwMSwgMi4zNzI4MzIyOTgyNzg4MDg2XSwgWzQ4Ljg2MDgwNDU2MDc1NTY3LCAyLjM3Mjc2NzkyNTI2MjQ1MV1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwYzAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiMwYzAiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvZmZzZXQiOiAzLjUsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA2fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfNjZkM2IzOGI0YjQzNDhjZmE5MDQwMGJhZmI1MGE0NTUpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfb2Zmc2V0XzhjZjRkOWQzZGQ3MzQ3MjZiNGM1MjNmYjEzOTNhYzEzID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY2NTM1NjUzNjkzOTYsIDIuMzY0NzQyNzU1ODg5ODkyNl0sIFs0OC44NjYzMDk4MTAyMzY5NCwgMi4zNjQ3NjQyMTM1NjIwMTE3XSwgWzQ4Ljg2MzE0Nzg5NDgxNjEyLCAyLjM2NjY3Mzk0NjM4MDYxNTJdLCBbNDguODYwNjYzMzkyNTQ5NDQsIDIuMzY3MzE3Njc2NTQ0MTg5NV1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogInJlZCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAicmVkIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogMC4wLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzY2ZDNiMzhiNGI0MzQ4Y2ZhOTA0MDBiYWZiNTBhNDU1KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF84YTQ3MmZlNDNkMjA0MWFiYjhkMjk0OTMyMzViYzg0YSA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdLCBbNDguODY2NTM1NjUzNjkzOTYsIDIuMzY0NzQyNzU1ODg5ODkyNl1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogInJlZCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAicmVkIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogLTEwLjUsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA2fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfNjZkM2IzOGI0YjQzNDhjZmE5MDQwMGJhZmI1MGE0NTUpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfb2Zmc2V0XzU0YzlkZmIwNzUzNTRjNjdiMjFhZWU5MWYxNTkxNTk4ID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M10sIFs0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzA4ZiIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiIzA4ZiIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9mZnNldCI6IC0zLjUsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA2fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfNjZkM2IzOGI0YjQzNDhjZmE5MDQwMGJhZmI1MGE0NTUpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfb2Zmc2V0X2ZiZmViMTkzNjQ0ODRkNWY5NWEzODdjZWJkMzA2ZWIxID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M10sIFs0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzBjMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogZmFsc2UsICJmaWxsQ29sb3IiOiAiIzBjMCIsICJmaWxsT3BhY2l0eSI6IDAuMiwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJub0NsaXAiOiBmYWxzZSwgIm9mZnNldCI6IDMuNSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDZ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF82NmQzYjM4YjRiNDM0OGNmYTkwNDAwYmFmYjUwYTQ1NSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9vZmZzZXRfODgxNDAzMzU1MjY2NGViZmFlZDk4ZGEyMDlkMzM4MDUgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjczNTQzMjc2ODEzMSwgMi4zNjMzMjY1NDk1MzAwMjkzXSwgWzQ4Ljg2NjUzNTY1MzY5Mzk2LCAyLjM2NDc0Mjc1NTg4OTg5MjZdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZjgwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjZjgwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogMTAuNSwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDZ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF82NmQzYjM4YjRiNDM0OGNmYTkwNDAwYmFmYjUwYTQ1NSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9vZmZzZXRfZjE0NTAxZTE1YmYwNGJjZDlhZWM3OThhZTMxZjJhNTcgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XSwgWzQ4Ljg2NjYwNjIyOTU2NTI0LCAyLjM2NTAwMDI0Nzk1NTMyMjNdLCBbNDguODY2OTg3MzM3NTUwMTY0LCAyLjM2NTUwOTg2NzY2ODE1Ml0sIFs0OC44NjYxOTE1OTQ4OTYwMywgMi4zNjk2MjcwNTg1MDYwMTJdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDhmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMDhmIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogLTcuMCwgIm9wYWNpdHkiOiAxLCAic21vb3RoRmFjdG9yIjogMS4wLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDZ9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF82NmQzYjM4YjRiNDM0OGNmYTkwNDAwYmFmYjUwYTQ1NSk7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHBvbHlfbGluZV9vZmZzZXRfNWEwNWEyNDRlNzc5NDA4ZDhhNDk2ZTUzYWQxN2E0ZWYgPSBMLnBvbHlsaW5lKAogICAgICAgICAgICAgICAgW1s0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XSwgWzQ4Ljg2NjYwNjIyOTU2NTI0LCAyLjM2NTAwMDI0Nzk1NTMyMjNdLCBbNDguODY2OTg3MzM3NTUwMTY0LCAyLjM2NTUwOTg2NzY2ODE1Ml0sIFs0OC44NjYxOTE1OTQ4OTYwMywgMi4zNjk2MjcwNTg1MDYwMTJdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMGMwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMGMwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogMC4wLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzY2ZDNiMzhiNGI0MzQ4Y2ZhOTA0MDBiYWZiNTBhNDU1KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lX29mZnNldF8wOWI1ZmZjZTU0NTE0ZWQyYTZhYzAwZDg4NWJhZTRiMCA9IEwucG9seWxpbmUoCiAgICAgICAgICAgICAgICBbWzQ4Ljg2NjUzNTY1MzY5Mzk2LCAyLjM2NDc0Mjc1NTg4OTg5MjZdLCBbNDguODY2NjA2MjI5NTY1MjQsIDIuMzY1MDAwMjQ3OTU1MzIyM10sIFs0OC44NjY5ODczMzc1NTAxNjQsIDIuMzY1NTA5ODY3NjY4MTUyXSwgWzQ4Ljg2NjE5MTU5NDg5NjAzLCAyLjM2OTYyNzA1ODUwNjAxMl1dLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiNmODAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IGZhbHNlLCAiZmlsbENvbG9yIjogIiNmODAiLCAiZmlsbE9wYWNpdHkiOiAwLjIsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAibm9DbGlwIjogZmFsc2UsICJvZmZzZXQiOiA3LjAsICJvcGFjaXR5IjogMSwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA2fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfNjZkM2IzOGI0YjQzNDhjZmE5MDQwMGJhZmI1MGE0NTUpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBwb2x5X2xpbmVfb2Zmc2V0XzAwODU4YjU0MDE5OTRjOWE5ZWE5YmRiM2JmMGU3Yzc0ID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbNDguODY2MTkxNTk0ODk2MDMsIDIuMzY5NjI3MDU4NTA2MDEyXSwgWzQ4Ljg2NTcwMjg1MDg5NTc0NCwgMi4zNzIzNDk1MDA2NTYxMjhdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjZjgwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjZjgwIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib2Zmc2V0IjogMC4wLCAib3BhY2l0eSI6IDEsICJzbW9vdGhGYWN0b3IiOiAxLjAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNn0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwXzY2ZDNiMzhiNGI0MzQ4Y2ZhOTA0MDBiYWZiNTBhNDU1KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgZmVhdHVyZV9ncm91cF9jNDY4N2YzYTNlODM0NGQyODkxODc3NjkyZWRkNWEyZiA9IEwuZmVhdHVyZUdyb3VwKAogICAgICAgICAgICAgICAge30KICAgICAgICAgICAgKS5hZGRUbyhtYXBfMzY5MDY3MGYwODQxNDI4N2FjMWZmN2RjZGIwZWQ1ZjgpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzhiMTk1MTRiNjljMTRjODVhNzRmMzg1NWVmN2RiOTk2ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguODc2MjE3NzMzMjQxNTMsIDIuMzU3OTE5MjE2MTU2MDA2XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNjY2MiLCAiZmlsbE9wYWNpdHkiOiAxLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLCAicmFkaXVzIjogMTAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwX2M0Njg3ZjNhM2U4MzQ0ZDI4OTE4Nzc2OTJlZGQ1YTJmKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9mMzFmZDNiNzg4NmU0MjQzYTNkY2ExYTk3YjBhYzIyYyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2NjYyIsICJmaWxsT3BhY2l0eSI6IDEsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEsICJyYWRpdXMiOiAxMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA0fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfYzQ2ODdmM2EzZTgzNDRkMjg5MTg3NzY5MmVkZDVhMmYpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzRkMmU1Y2VmMmFkODQ5ZWI5ZDI3NmYyYzhjMjZlZTg0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguODY0NDM5NTA0OTM4MjMsIDIuMzUxNTAzMzcyMTkyMzgzXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNjY2MiLCAiZmlsbE9wYWNpdHkiOiAxLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLCAicmFkaXVzIjogMTAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwX2M0Njg3ZjNhM2U4MzQ0ZDI4OTE4Nzc2OTJlZGQ1YTJmKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl8zMTRjZjczZGFmMjA0NzlkYjkxZGRlNmYxM2VlYmQxNCA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg2NzM1NDMyNzY4MTMxLCAyLjM2MzMyNjU0OTUzMDAyOTNdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2NjYyIsICJmaWxsT3BhY2l0eSI6IDEsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEsICJyYWRpdXMiOiAxMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA0fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfYzQ2ODdmM2EzZTgzNDRkMjg5MTg3NzY5MmVkZDVhMmYpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyXzMxYjc0ZDA2N2IzNTQ5MDI5NDdhOGY4ZjllYWVmOWNkID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguODY2MTkxNTk0ODk2MDMsIDIuMzY5NjI3MDU4NTA2MDEyXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNjY2MiLCAiZmlsbE9wYWNpdHkiOiAxLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLCAicmFkaXVzIjogMTAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwX2M0Njg3ZjNhM2U4MzQ0ZDI4OTE4Nzc2OTJlZGQ1YTJmKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl85MmIxMmQzZWIwZWI0ZDNmODU2MDVjNzM3YjRjNGI3YyA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg2MDgwNDU2MDc1NTY3LCAyLjM3Mjc2NzkyNTI2MjQ1MV0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjY2NjIiwgImZpbGxPcGFjaXR5IjogMSwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMSwgInJhZGl1cyI6IDEwLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDR9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF9jNDY4N2YzYTNlODM0NGQyODkxODc3NjkyZWRkNWEyZik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfMGU1ZDlhMzYzZDQ1NGZiMThhNjEyMDEzODM4MGE1YWEgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNjY2MiLCAiZmlsbE9wYWNpdHkiOiAxLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLCAicmFkaXVzIjogMTAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwX2M0Njg3ZjNhM2U4MzQ0ZDI4OTE4Nzc2OTJlZGQ1YTJmKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl84MzgyYWU0NThmNWM0MmIwYTI2NzQwMGY1MjRlNzE4YSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg2MDY2MzM5MjU0OTQ0LCAyLjM2NzMxNzY3NjU0NDE4OTVdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2NjYyIsICJmaWxsT3BhY2l0eSI6IDEsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEsICJyYWRpdXMiOiAxMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA0fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfYzQ2ODdmM2EzZTgzNDRkMjg5MTg3NzY5MmVkZDVhMmYpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2NmYjg4ZTE3MzlkYjQ2MTc5YzhlMzJkMmZiMTFkMTc4ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguODY3MzU0MzI3NjgxMzEsIDIuMzYzMzI2NTQ5NTMwMDI5M10sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjY2NjIiwgImZpbGxPcGFjaXR5IjogMSwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMSwgInJhZGl1cyI6IDEwLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDR9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF9jNDY4N2YzYTNlODM0NGQyODkxODc3NjkyZWRkNWEyZik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNWEzNGUyNmZiYjYwNGM1OWJlOWNmMTMwNDk3ODk4M2EgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC44NjY1MzU2NTM2OTM5NiwgMi4zNjQ3NDI3NTU4ODk4OTI2XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNjY2MiLCAiZmlsbE9wYWNpdHkiOiAxLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLCAicmFkaXVzIjogMTAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwX2M0Njg3ZjNhM2U4MzQ0ZDI4OTE4Nzc2OTJlZGQ1YTJmKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl80YmQyYzlhMmVmYjU0ZTFiYmIxMWM5YzcxOGYzMDgyOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg2NjUzNTY1MzY5Mzk2LCAyLjM2NDc0Mjc1NTg4OTg5MjZdLAogICAgICAgICAgICAgICAgeyJidWJibGluZ01vdXNlRXZlbnRzIjogdHJ1ZSwgImNvbG9yIjogIiMwMDAiLCAiZGFzaEFycmF5IjogbnVsbCwgImRhc2hPZmZzZXQiOiBudWxsLCAiZmlsbCI6IHRydWUsICJmaWxsQ29sb3IiOiAiI2NjYyIsICJmaWxsT3BhY2l0eSI6IDEsICJmaWxsUnVsZSI6ICJldmVub2RkIiwgImxpbmVDYXAiOiAicm91bmQiLCAibGluZUpvaW4iOiAicm91bmQiLCAib3BhY2l0eSI6IDEsICJyYWRpdXMiOiAxMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiA0fQogICAgICAgICAgICApLmFkZFRvKGZlYXR1cmVfZ3JvdXBfYzQ2ODdmM2EzZTgzNDRkMjg5MTg3NzY5MmVkZDVhMmYpOwogICAgICAgIAogICAgCiAgICAgICAgICAgIHZhciBjaXJjbGVfbWFya2VyX2IxMjExZjJhMzg5MTQ3YWZiYWZmNTdhZWNhODQxMWY0ID0gTC5jaXJjbGVNYXJrZXIoCiAgICAgICAgICAgICAgICBbNDguODY2MTkxNTk0ODk2MDMsIDIuMzY5NjI3MDU4NTA2MDEyXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNjY2MiLCAiZmlsbE9wYWNpdHkiOiAxLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLCAicmFkaXVzIjogMTAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwX2M0Njg3ZjNhM2U4MzQ0ZDI4OTE4Nzc2OTJlZGQ1YTJmKTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgY2lyY2xlX21hcmtlcl9iODgwMjQxZGVmMTI0ZDU1YThiZTQwMTcxZDBiMDQyOSA9IEwuY2lyY2xlTWFya2VyKAogICAgICAgICAgICAgICAgWzQ4Ljg2NjE5MTU5NDg5NjAzLCAyLjM2OTYyNzA1ODUwNjAxMl0sCiAgICAgICAgICAgICAgICB7ImJ1YmJsaW5nTW91c2VFdmVudHMiOiB0cnVlLCAiY29sb3IiOiAiIzAwMCIsICJkYXNoQXJyYXkiOiBudWxsLCAiZGFzaE9mZnNldCI6IG51bGwsICJmaWxsIjogdHJ1ZSwgImZpbGxDb2xvciI6ICIjY2NjIiwgImZpbGxPcGFjaXR5IjogMSwgImZpbGxSdWxlIjogImV2ZW5vZGQiLCAibGluZUNhcCI6ICJyb3VuZCIsICJsaW5lSm9pbiI6ICJyb3VuZCIsICJvcGFjaXR5IjogMSwgInJhZGl1cyI6IDEwLCAic3Ryb2tlIjogdHJ1ZSwgIndlaWdodCI6IDR9CiAgICAgICAgICAgICkuYWRkVG8oZmVhdHVyZV9ncm91cF9jNDY4N2YzYTNlODM0NGQyODkxODc3NjkyZWRkNWEyZik7CiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIGNpcmNsZV9tYXJrZXJfNzcyNTNiZDY0MDExNDdmOWJhYjRmOGUxMWMyMjg0Y2QgPSBMLmNpcmNsZU1hcmtlcigKICAgICAgICAgICAgICAgIFs0OC44NjU3MDI4NTA4OTU3NDQsIDIuMzcyMzQ5NTAwNjU2MTI4XSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMDAwIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiB0cnVlLCAiZmlsbENvbG9yIjogIiNjY2MiLCAiZmlsbE9wYWNpdHkiOiAxLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm9wYWNpdHkiOiAxLCAicmFkaXVzIjogMTAsICJzdHJva2UiOiB0cnVlLCAid2VpZ2h0IjogNH0KICAgICAgICAgICAgKS5hZGRUbyhmZWF0dXJlX2dyb3VwX2M0Njg3ZjNhM2U4MzQ0ZDI4OTE4Nzc2OTJlZGQ1YTJmKTsKICAgICAgICAKPC9zY3JpcHQ+ onload=\"this.contentDocument.open();this.contentDocument.write(atob(this.getAttribute('data-html')));this.contentDocument.close();\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>"
      ],
      "text/plain": [
       "<folium.folium.Map at 0x1f66874e1c8>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m = folium.Map(location=[48.868, 2.365], zoom_start=15)\n",
    "\n",
    "geojson = {\n",
    "    \"type\": \"FeatureCollection\",\n",
    "    \"features\": [\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [0, 1]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.357919216156006, 48.87621773324153],\n",
    "                    [2.357339859008789, 48.874834693731664],\n",
    "                    [2.362983226776123, 48.86855408432749],\n",
    "                    [2.362382411956787, 48.86796126699168],\n",
    "                    [2.3633265495300293, 48.86735432768131],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [2, 3]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.351503372192383, 48.86443950493823],\n",
    "                    [2.361609935760498, 48.866775611250205],\n",
    "                    [2.3633265495300293, 48.86735432768131],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [1, 2]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.369627058506012, 48.86619159489603],\n",
    "                    [2.3724031448364253, 48.8626397112042],\n",
    "                    [2.3728322982788086, 48.8616233285001],\n",
    "                    [2.372767925262451, 48.86080456075567],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [0]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.3647427558898926, 48.86653565369396],\n",
    "                    [2.3647642135620117, 48.86630981023694],\n",
    "                    [2.3666739463806152, 48.86314789481612],\n",
    "                    [2.3673176765441895, 48.86066339254944],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [0, 1, 2, 3]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.3633265495300293, 48.86735432768131],\n",
    "                    [2.3647427558898926, 48.86653565369396],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [1, 2, 3]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.3647427558898926, 48.86653565369396],\n",
    "                    [2.3650002479553223, 48.86660622956524],\n",
    "                    [2.365509867668152, 48.866987337550164],\n",
    "                    [2.369627058506012, 48.86619159489603],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "        {\n",
    "            \"type\": \"Feature\",\n",
    "            \"properties\": {\"lines\": [3]},\n",
    "            \"geometry\": {\n",
    "                \"type\": \"LineString\",\n",
    "                \"coordinates\": [\n",
    "                    [2.369627058506012, 48.86619159489603],\n",
    "                    [2.372349500656128, 48.865702850895744],\n",
    "                ],\n",
    "            },\n",
    "        },\n",
    "    ],\n",
    "}\n",
    "\n",
    "# manage overlays in groups to ease superposition order\n",
    "outlines = folium.FeatureGroup(\"outlines\")\n",
    "line_bg = folium.FeatureGroup(\"lineBg\")\n",
    "bus_lines = folium.FeatureGroup(\"busLines\")\n",
    "bus_stops = folium.FeatureGroup(\"busStops\")\n",
    "\n",
    "line_weight = 6\n",
    "line_colors = [\"red\", \"#08f\", \"#0c0\", \"#f80\"]\n",
    "stops = []\n",
    "for line_segment in geojson[\"features\"]:\n",
    "    # Get every bus line coordinates\n",
    "    segment_coords = [[x[1], x[0]] for x in line_segment[\"geometry\"][\"coordinates\"]]\n",
    "    # Get bus stops coordinates\n",
    "    stops.append(segment_coords[0])\n",
    "    stops.append(segment_coords[-1])\n",
    "    # Get number of bus lines sharing the same coordinates\n",
    "    lines_on_segment = line_segment[\"properties\"][\"lines\"]\n",
    "    # Width of segment proportional to the number of bus lines\n",
    "    segment_width = len(lines_on_segment) * (line_weight + 1)\n",
    "    # For the white and black outline effect\n",
    "    folium.PolyLine(\n",
    "        segment_coords, color=\"#000\", weight=segment_width + 5, opacity=1\n",
    "    ).add_to(outlines)\n",
    "    folium.PolyLine(\n",
    "        segment_coords, color=\"#fff\", weight=segment_width + 3, opacity=1\n",
    "    ).add_to(line_bg)\n",
    "    # Draw parallel bus lines with different color and offset\n",
    "    for j, line_number in enumerate(lines_on_segment):\n",
    "        plugins.PolyLineOffset(\n",
    "            segment_coords,\n",
    "            color=line_colors[line_number],\n",
    "            weight=line_weight,\n",
    "            opacity=1,\n",
    "            offset=j * (line_weight + 1) - (segment_width / 2) + ((line_weight + 1) / 2),\n",
    "        ).add_to(bus_lines)\n",
    "\n",
    "# Draw bus stops\n",
    "for stop in stops:\n",
    "    folium.CircleMarker(\n",
    "        stop,\n",
    "        color=\"#000\",\n",
    "        fill_color=\"#ccc\",\n",
    "        fill_opacity=1,\n",
    "        radius=10,\n",
    "        weight=4,\n",
    "        opacity=1,\n",
    "    ).add_to(bus_stops)\n",
    "    \n",
    "outlines.add_to(m)\n",
    "line_bg.add_to(m)\n",
    "bus_lines.add_to(m)\n",
    "bus_stops.add_to(m)\n",
    "\n",
    "m.save(os.path.join('results', \"PolyLineOffset_bus.html\"))\n",
    "\n",
    "m"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
